﻿using HSDc.RingleFlow.Kernel.Util;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Transactions;

namespace HSDc.RingleFlow.Kernel.DBPersit.Dao
{
    internal class RepositoryServiceDao
    {
        internal HSDc.RingleFlow.Kernel.Dto.ProcessDefinition.ProcessDefinition QueryProcessDefinition(
            string ProcessDefinitionName)
        {
            RingleFlowEntities entity = Util.ConnectionFactory.GetInstance().GetEntities();
            var pd = (from p in entity.ProcessDefinitionDto
                      where p.Definition_Name == ProcessDefinitionName
                      orderby p.Definition_Version descending
                      select new HSDc.RingleFlow.Kernel.Dto.ProcessDefinition.ProcessDefinition()
                      {
                          Id = p.Definition_GUID,
                          Name = p.Definition_Name,
                          Version = p.Definition_Version
                      }).Take(1).FirstOrDefault();
            return pd;
        }

        internal void SaveProcessDefinition(
            HSDc.RingleFlow.Kernel.Dto.ProcessDefinition.ProcessDefinition pd)
        {
            using (RingleFlowEntities entity = Util.ConnectionFactory.GetInstance().GetEntities())
            {
                using (var trans = new TransactionScope())
                {
                    ProcessDefinitionDto def = CreateDefinition(pd);
                    entity.ProcessDefinitionDto.AddObject(def);
                    entity.SaveChanges();
                    int defId = def.Definition_ID;
                    pd.Swimlanes.ForEach(s => entity.SwimlaneDto.AddObject(CreateSwimlane(s, defId)));
                    entity.SaveChanges();
                    pd.Activities.ForEach(
                        delegate(HSDc.RingleFlow.Kernel.Dto.ProcessDefinition.Activity a)
                        {
                            ProcessActivityDto ac = CreateActivity(a, defId);
                            entity.ProcessActivityDto.AddObject(ac);
                            entity.SaveChanges();
                            a.RealId = ac.Activity_ID;
                        }
                    );
                    pd.Activities.ForEach(a => a.OutboundTransitions.ForEach(ts => entity.TransitionDto.AddObject(CreateTransition(ts))));
                    entity.SaveChanges();
                    trans.Complete();
                }
            }
        }

        private ProcessDefinitionDto CreateDefinition(
            HSDc.RingleFlow.Kernel.Dto.ProcessDefinition.ProcessDefinition pd)
        {
            return new ProcessDefinitionDto()
            {
                Definition_Name = pd.Name,
                Definition_Version = pd.Version,
                Definition_GUID = pd.Id,
                Definition_ACTIVE = pd.Enabled,
                Definition_STATUS = Convert.ToInt32(pd.Enabled)
            };
        }

        private SwimlaneDto CreateSwimlane(
            HSDc.RingleFlow.Kernel.Dto.ProcessDefinition.Swimlane s, int pdId)
        {
            return new SwimlaneDto()
            {
                Swimlane_Definition_ID = pdId,
                Swimlane_SEQ = s.Seq,
                Swimlane_GUID = s.Id,
                Swimlane_Name = s.Name,
                Swimlane_RULE_CLASS = s.RuleClassName
            };
        }

        private ProcessActivityDto CreateActivity(
            HSDc.RingleFlow.Kernel.Dto.ProcessDefinition.Activity a, int pdId)
        {
            return new ProcessActivityDto()
            {
                Activity_Name = a.Name,
                Activity_GUID = a.Id,
                Activity_CLASS = EnumUtils.stringValueOf(a.Type),
                Activity_RULE_CLASS = a.RuleClassName,
                Activity_Belong_Definition = pdId,
                Actvity_Swimlane = a.Swimlane.Seq
            };
        }

        private TransitionDto CreateTransition(
            HSDc.RingleFlow.Kernel.Dto.ProcessDefinition.Transition ts)
        {
            return new TransitionDto()
            {
                Transition_GUID = ts.Id,
                Transition_Source = ts.Source.RealId,
                Transition_Target = ts.Target.RealId
            };
        }

        internal ProcessDefinitionDto GetProcessDefinition(string definitionId)
        {
            RingleFlowEntities entity = Util.ConnectionFactory.GetInstance().GetEntities();
            var definition = from pd in entity.ProcessDefinitionDto
                             where (pd.Definition_GUID.ToLower() == definitionId.ToLower())
                             select pd;
            return definition.First();
        }

        internal ProcessDefinitionDto GetProcessDefinitionByName(string definitionName)
        {
            RingleFlowEntities entity = Util.ConnectionFactory.GetInstance().GetEntities();
            var definition = from pd in entity.ProcessDefinitionDto
                             where ((pd.Definition_Name == definitionName) &&
                                        (pd.Definition_ACTIVE))
                             orderby pd.Definition_Version descending
                             select pd;
            return definition.First();
        }

        internal int GetActiveProcessInstance(int definitionId)
        {
            return 0;
        }

        internal List<ProcessActivityDto> GetDefaultActivities(int definitionId)
        {
            RingleFlowEntities entity = Util.ConnectionFactory.GetInstance().GetEntities();
            var acts = from pa in entity.ProcessActivityDto
                             where (pa.Activity_Belong_Definition==definitionId)
                             orderby pa.Activity_ID
                             select pa;
            return acts.ToList();
        }

        internal List<TransitionDto> GetTransitionsBySource(int sourceActId)
        {
            RingleFlowEntities entity = Util.ConnectionFactory.GetInstance().GetEntities();
            var trans = from pa in entity.TransitionDto
                       where (pa.Transition_Source == sourceActId)
                       orderby pa.Transition_ID
                       select pa;
            return trans.ToList();
        }

        internal SwimlaneDto GetActivityBelongSwimlane(int activityId)
        {
            RingleFlowEntities entity = Util.ConnectionFactory.GetInstance().GetEntities();
            var activity = (from pa in entity.ProcessActivityDto
                         where pa.Activity_ID == activityId
                         select pa).Single();
            var swimlane = (from sl in entity.SwimlaneDto
                            where ((sl.Swimlane_Definition_ID == activity.Activity_Belong_Definition) &&
                                       (sl.Swimlane_SEQ == activity.Actvity_Swimlane))
                            select sl).Single();
            return swimlane;
        }

        internal int GetOrgType(string swimlaneGuid)
        {
            RingleFlowEntities entity = Util.ConnectionFactory.GetInstance().GetEntities();
            int oType;
            var orgType = from or in entity.OrganizationDto
                          join sl in entity.SwimlaneDto on or.Org_ID equals sl.Swimlane_Org_ID
                          where sl.Swimlane_GUID == swimlaneGuid
                          select or.Org_TYPE;
            if (orgType.ToList().Count == 0) oType = 0;
            else oType = orgType.First();
            return oType;
        }
    }
}
